<?php
require_once 'config.php'; 

/**
 * This class abstracts the DB connection from the implementation.
 * It is implemented as a singleton.
 */
final class DB
{
	/**
	 * Gets the singleton instance of the class.
	 *
	 * Note that this function is not thread-safe.
	 *
	 * @return
	 * 		   The singleton instance of the class
	 */
	public static function getInstance() /*DB*/
	{
		if (!self::$instance)
		{
			self::$instance = new self();
		}
		return self::$instance;
	}
	
	/**
	 * Escapes the given string so it can be stored properly in the DB.
	 * 
	 * @param string $value
	 * 		  The value to be escaped.
	 * 
	 * @return
	 * 		  The escaped string value.
	 */
	public static function escapeString(/*string*/ $value)
	{
		return DB::escape($value, 'string');
	}
	
	/**
	 * Escapes the given integer so it can be stored properly in the DB.
	 *
	 * @param int $value
	 * 		  The value to be escaped.
	 *
	 * @return
	 * 		  The escaped integer value.
	 */
	public static function escapeInt(/*int*/ $value)
	{
		return DB::escape($value, 'int');
	}
	
	/**
	 * Escapes the given value so it can be stored properly in the DB.
	 * 
	 * @param type $value
	 * 		  The value to be escaped.
	 * 
	 * @param string $type
	 * 		  The type of the value.
	 * 
	 * @return
	 * 		  The escaped value with the same type as the input.
	 */
	public static function escape(/*type*/ $value, /*string*/ $type) /*type*/
	{
		switch ($type)
		{
			case 'int': 
				return (int) $value;
			case 'string':
				if (get_magic_quotes_gpc())
				{
					$value = stripcslashes($value);
				}
				return '\'' . mysql_real_escape_string(htmlentities($value)) . '\'';
			default:
				return $value;
		}
	}
	
	private static $instance; /*DB*/

	private function __construct() /*DB*/
	{
	}
	
	/**
	 * Executes a stored procedure.
	 * 
	 * @param string $procedureName
	 * 		  The name of the procedure which will be executed.
	 * 
	 * @param array $inParameters
	 * 		  An array of input parameters passed to the procedure.
	 * 
	 * @param array $outParameters
	 * 		  An array of the output parameters names passed to the procedure.
	 * 
	 * @return
	 * 		  A resource holding the out parameters of the procedure.
	 */
	public function executeProcedure(/*string*/ $procedureName, 
			/*array*/ $inParameters, /*array*/ $outParameters = array()) /*resource*/
	{
		// TODO: Handle invalid connection.
		// TODO: Investigate why there are problems when keeping just one connection.
		$connection = mysql_connect(DB_HOST, DB_USER, DB_PASS);
		mysql_select_db(DB_NAME, $connection);
		
		/*string*/ $parameters = '';
		/*int*/ $inParametersCount = count($inParameters);
		/*int*/ $outParametersCount = count($outParameters);
		/*int*/ $parametersCount = $inParametersCount + $outParametersCount;
		/*int*/ $parameterIndex = 1;
		foreach ($inParameters as $inParameter)
		{
			$parameters = $parameters . $inParameter;
			if ($parameterIndex < $parametersCount)
			{
				$parameters = $parameters . ', ';
			}
			$parameterIndex++;
		}
		
		/*string*/ $selectParameters = '';
		foreach ($outParameters as $outParameter)
		{
			$parameters = $parameters . '@' . $outParameter;
			$selectParameters = $selectParameters . '@' . $outParameter . ' AS ' . $outParameter;
			if ($parameterIndex < $parametersCount)
			{
				$parameters = $parameters . ', ';
				$selectParameters = $selectParameters . ', ';
			}
			$parameterIndex++;
		}
		
		/*string*/ $callStatement = 'CALL ' . $procedureName . '(' . $parameters . ');';
		/*resource*/ $result = mysql_query($callStatement);
		if ($outParametersCount > 0)
		{
			$result = mysql_query('SELECT ' . $selectParameters . ';');
		}
		
		mysql_close($connection);
		return $result;
	}
	
	/**
	 * Gets the next row of the given resource.
	 * 
	 * @param resource $resource
	 * 		  The resource to fetch the data from.
	 * 
	 * @return
	 * 		  An associative array holding the next row of the data.
	 */
	public function getNextRow(/*resource*/ $resource) /*array*/
	{
		return mysql_fetch_assoc($resource);
	}
} // end class
?>